Balanced Parentheses (hard)
We'll cover the following
Solution #
This problem follows the Subsets pattern and can be mapped to Permutations. We can follow a similar BFS approach.
Let’s take Example-2 mentioned above to generate all the combinations of balanced parentheses. Following a BFS approach, we will keep adding open parentheses (
or close parentheses )
. At each step we need to keep two things in mind:
- We can’t add more than ‘N’ open parenthesis.
- To keep the parentheses balanced, we can add a close parenthesis
)
only when we have already added enough open parenthesis(
. For this, we can keep a count of open and close parenthesis with every combination.
Following this guideline, let’s generate parentheses for N=3:
- Start with an empty combination: “”
- At every step, let’s take all combinations of the previous step and add
(
or)
keeping the above-mentioned two rules in mind. - For the empty combination, we can add
(
since the count of open parenthesis will be less than ‘N’. We can’t add)
as we don’t have an equivalent open parenthesis, so our list of combinations will now be: “(” - For the next iteration, let’s take all combinations of the previous set. For “(” we can add another
(
to it since the count of open parenthesis will be less than ‘N’. We can also add)
as we do have an equivalent open parenthesis, so our list of combinations will be: “((”, “()” - In the next iteration, for the first combination “((”, we can add another
(
to it as the count of open parenthesis will be less than ‘N’, we can also add)
as we do have an equivalent open parenthesis. This gives us two new combinations: “(((” and “(()”. For the second combination “()”, we can add another(
to it since the count of open parenthesis will be less than ‘N’. We can’t add)
as we don’t have an equivalent open parenthesis, so our list of combinations will be: “(((”, “(()”, ()(" - Following the same approach, next we will get the following list of combinations: “((()”, “(()(”, “(())”, “()((”, “()()”
- Next we will get: “((())”, “(()()”, “(())(”, “()(()”, “()()(”
- Finally, we will have the following combinations of balanced parentheses: “((()))”, “(()())”, “(())()”, “()(())”, “()()()”
- We can’t add more parentheses to any of the combinations, so we stop here.
Here is the visual representation of this algorithm:
Code #
Here is what our algorithm will look like:
Time complexity #
Let’s try to estimate how many combinations we can have for ‘N’ pairs of balanced parentheses. If we don’t care for the ordering - that )
can only come after (
- then we have two options for every position, i.e., either put open parentheses or close parentheses. This means we can have a maximum of combinations. Because of the ordering, the actual number will be less than .
If you see the visual representation of Example-2 closely you will realize that, in the worst case, it is equivalent to a binary tree, where each node will have two children. This means that we will have leaf nodes and intermediate nodes. So the total number of elements pushed to the queue will be + which is asymptotically equivalent to . While processing each element, we do need to concatenate the current string with (
or )
. This operation will take , so the overall time complexity of our algorithm will be . This is not completely accurate but reasonable enough to be presented in the interview.
The actual time complexity ( ) is bounded by the Catalan number and is beyond the scope of a coding interview. See more details here.
Space complexity #
All the additional space used by our algorithm is for the output list. Since we can’t have more than combinations, the space complexity of our algorithm is .
Recursive Solution #
Here is the recursive algorithm following a similar approach: